package model.turtle;

import java.awt.Color;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import controller.Controller;

/**
 * The turtle class. myDirection is an non-negative integer smaller or equal to
 * 360.
 */
public class Turtle {
    private List<Position> trail;
    private Position position;
    private boolean penDown;
    private boolean show;
    private boolean active;
    private int backGround;
    private int penColor;
    private int penSize;
    private int shape;
    private static List<Color> colorList;

    /**
     * Build a new turtle.
     * 
     * @param x
     * @param y
     * @param direction
     */

    public Turtle(Position pos) {
        position = new Position(pos);
        trail = new LinkedList<Position>();
        trail.add(pos);

        show = true;
        penDown = true;
        active = false;
        backGround = 0;
        penColor = 0;
        penSize = 0;
        shape = 0;
        colorList = new ArrayList<Color>();
        colorList.add(Color.black);
    }

    public int setBackground(int b) {
        backGround = b;
        return b;
    }

    public int setPenColor(int p) {
        penColor = p;
        return p;
    }

    public int setPenSize(int s) {
        penSize = s;
        return s;
    }

    public int setShape(int s) {
        shape = s;
        return s;
    }

    public void setActive(boolean active) {
        this.active = active;
    }

    public boolean getActive() {
        return active;
    }

    /**
     * @return the penDown
     */
    public Integer isPenDown() {
        if (penDown)
            return 1;
        else
            return 0;
    }

    /**
     * @param penDown
     *            the penDown to set
     */
    public Integer setPenDown() {
        penDown = true;
        return 1;
    }

    public Integer setPenUp() {
        penDown = false;
        return 0;
    }

    /**
     * @return the show
     */
    public Integer isShow() {
        if (show)
            return 1;
        else
            return 0;
    }

    /**
     * @param show
     *            the show to set
     */
    public Integer setShow() {
        show = true;
        return 1;
    }

    public Integer setNotShow() {
        show = false;
        return 0;
    }

    /**
     * @return the myDirection
     */
    public int getDirection() {
        return position.getDirection();
    }

    /**
     * @param myDirection
     *            the myDirection to set
     */
    public Integer setDirection(int myDirection) {
        position.setDirection(myDirection);
        buildTrail();
        return myDirection;
    }

    /**
     * @return the position of the turtle.
     */
    public Position getPosition() {
        return position;
    }

    /**
     * Get the list of trail.
     * 
     * @return
     */
    public List<Position> getTrail() {
        return trail;
    }

    public void addTrail(int x, int y, int d) {
        trail.add(new Position(x, y, d % 360));
    }

    public int forward(int d) {
        position.x = position.x
                + Math.cos((position.direction * Math.PI) / 180.0) * (double) d;
        position.y = position.y
                + Math.sin((position.direction * Math.PI) / 180.0) * (double) d;
        buildTrail();
        return d;
    }

    public Integer back(int d) {
        forward(-d);
        reverseDirection();
        return d;
    }

    public void reverseDirection() {
        if (position.getDirection() >= 180)
            position.setDirection(position.getDirection() - 180);
        else
            position.setDirection(360 + (position.getDirection() - 180));
    }

    public int right(int d) {
        left(-d);
        return d;
    }

    public int left(int d) {
        position.setDirection(position.getDirection() + d);
        buildTrail();
        return d;
    }

    public void buildTrail() {
        trail.add(new Position(position.getX(), position.getY(), position
                .getDirection()));
    }

    public int home() {
        return setPosition(new Position(0, 0, 90));
    }

    public int setPosition(Position p) {
        int rtn = (int) (position.x + position.y);
        position.x = p.x;
        position.y = p.y;
        position.setDirection(p.getDirection());
        return rtn;
    }

    public int clearScreen() {
        int rtn = home();
        trail.clear();
        buildTrail();
        return rtn;
    }

    public int setXY(Integer x, Integer y) {
        int rtn = (int) (Math.abs(position.x - x) + Math.abs(position.y - y));
        position.x = x;
        position.y = y;
        return rtn;
    }

    public int getX() {
        return (int) Math.round(position.x);
    }

    public int getY() {
        return (int) Math.round(position.y);
    }

    public int getRandom(int max) {
        Random rand = new Random(max);
        return rand.nextInt();
    }

    public int towards(int x, int y) {
        if (x > position.x) {
            int deltaX = (int) (x - position.x);
            int deltaY = (int) (y - position.y);
            return (int) Math.acos(deltaY / deltaX);
        } else if (x < position.x) {
            int deltaX = (int) -(x - position.x);
            int deltaY = (int) (y - position.y);
            return (int) Math.acos(deltaY / deltaX);
        } else {
            if (y > position.y)
                return 90;
            if (y == position.y)
                return 0;
            else
                return 270;
        }
    }

    public int setPalette(int index, int r, int g, int b) {
        System.out.println("here");
        int size = colorList.size();
        if (size < (index + 1)) {
            for (int i = 0; i < (index + 1 - size); i++) {
                colorList.add(new Color(0, 0, 0));
            }
        }
        colorList.set(index, new Color(roundColorValue(r), roundColorValue(g),
                roundColorValue(b)));
        return index;
    }

    public int roundColorValue(int input) {
        if (input > 255)
            input = 255;
        else if (input < 0)
            input = 0;
        return input;
    }

    public String toString() {
        StringBuilder result = new StringBuilder();
        for (Position p : trail) {
            result.append(p.toString() + "\n");
        }
        return result.toString();
    }
}